package com.cskaoyan.controller;

import com.cskaoyan.bean.data.CartCheckedData;
import com.cskaoyan.bean.data.CartCheckoutData;
import com.cskaoyan.bean.vo.CartAddVo;
import com.cskaoyan.bean.data.CartIndexData;
import com.cskaoyan.bean.vo.BaseRespVo;
import com.cskaoyan.model.*;
import com.cskaoyan.service.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author Pudding
 * @Date 2024/6/13 16:40
 */
@RestController
@RequestMapping("wx/cart")
public class WxCartController {
    @Autowired
    CartService cartService;
    @Autowired
    CouponService couponService;
    @Autowired
    CouponUserService couponUserService;
    @Autowired
    AddressService addressService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    GrouponRulesService grouponRulesService;
    @Autowired
    SystemService systemService;

    //1. 根据用户用户id查询该用户的购物车中的货品数量
    @GetMapping("goodscount")
    public BaseRespVo goodsCount() {
        //没有登录的购物车数量显示为0
        int goodsCount = 0;

        //1.1 获取用户id
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();
            //1.2 根据用户id查询购物车中商品的总数
            goodsCount = cartService.goodsCount(userId);
        }
        return BaseRespVo.ok(goodsCount);
    }

    //2. 根据用户id查询购物车首页信息
    @GetMapping("index")
    public BaseRespVo index() {
        //2.1 获取用户id
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();
            //2.2 查看购物车首页，根据用户id查询当前用户的购物车记录，计算选中的商品(checked=1)的数量和金额
            CartIndexData data = cartService.cartIndex(userId);
            return BaseRespVo.ok(data);
        } else {
            return BaseRespVo.unAuthc();
        }
    }

    //3. 根据用户id添加到购物车中商品信息
    // 请求体中包含JSON字符串，使用@RequestBody来进行接收，将请求数据封装到CartAddVo对象中
    // 如果有这个商品在购物车中，则找到这条记录的number，对number进行相加(合并购物车操作)；如果没有的话，则新建记录
    @PostMapping("add")
    public BaseRespVo add(@RequestBody CartAddVo cartAddVo) {
        //获取userId
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();

            //1. 根据post请求参数，查询当前购物车中是否有对应商品记录
            MarketCart marketCart = cartService.findByPost(userId, cartAddVo.getGoodsId(), cartAddVo.getProductId());
            //1.1 如果没有该商品记录，就创建该购物车商品记录
            if (marketCart == null) {
                cartService.create(userId, cartAddVo);
            }
            //1.2 如果购物车有该商品记录，就更新订单数量和时间
            else {
                //1.3 构建新的购物车记录对象，等会作为更新的参数
                MarketCart updateCart = new MarketCart();
                updateCart.setId(marketCart.getId()); //获取id为了等会根据主键进行更新
                updateCart.setNumber((short) (marketCart.getNumber() + cartAddVo.getNumber()));
                updateCart.setUpdateTime(new Date());
                //1.4 按照新的购物车记录参数，更新原来购物车记录
                cartService.modify(updateCart);
            }
            //2. 返回购物车数量
            Integer num = cartService.goodsCount(userId);
            return BaseRespVo.ok(num);
        } else {
            return BaseRespVo.unAuthc();
        }
    }

    //4. 修改选中商品的选中状态(checked = !checked)，然后重新执行/wx/cart/index做的事情，返回结果类型一致
    @PostMapping("checked")
    public BaseRespVo checked(@RequestBody CartCheckedData cartCheckedData) {
        //获取userId
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();

            //1. 根据请求数据，更新商品的checked字段
            cartService.checked(userId, cartCheckedData);

            //2. 重新查询购物车首页信息
            return BaseRespVo.ok(cartService.cartIndex(userId));
        } else {
            return BaseRespVo.unAuthc();
        }
    }

    //5. 立即购买商品，如果购物车中已经有该商品了，可以覆盖掉
    @PostMapping("fastadd")
    public BaseRespVo fastadd(@RequestBody CartAddVo cartAddVo) {
        //获取userId
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();

            //1. 根据post请求参数，查询当前购物车中是否有对应商品记录
            MarketCart marketCart = cartService.findByPost(userId, cartAddVo.getGoodsId(), cartAddVo.getProductId());
            //1.1 如果购物车中已经有该商品了，可以覆盖掉
            if (marketCart != null) {
                cartService.deleteById(userId, cartAddVo.getGoodsId(), cartAddVo.getProductId());
            }
            //1.2 然后将该条记录插入到market_cart表中，之后进行购买
            cartService.create(userId, cartAddVo);

            //2. 查询该商品对应的market_cart表中该记录的id作为返回结果
            MarketCart cart = cartService.findByPost(userId, cartAddVo.getGoodsId(), cartAddVo.getProductId());
            return BaseRespVo.ok(cart.getId());
        } else {
            return BaseRespVo.unAuthc();
        }
    }

    @GetMapping("/checkout")
    public BaseRespVo checkout(Integer cartId, Integer addressId, Integer couponId, Integer userCouponId, Integer grouponRulesId) {
        // money为所有的钱
        BigDecimal money = new BigDecimal(0);
        CartCheckoutData cartCheckoutData = new CartCheckoutData();

        BigDecimal discount = new BigDecimal(0);
        // 如果是购物差下单则执行0否则通过前端传入的cartid来执行

        Subject subject = SecurityUtils.getSubject();

        Integer userId = (Integer) subject.getPrincipal();

        Map<String, String> systemConfig = systemService.toMap();
        //else两端的判定方式一模一样，除了订单返回一个是list，一个是具体对象，因为else后面会穿进去具体的cartId，返回的就是那个对象
        if (cartId.equals(0)) {
            // 得到地址，如果没有选择地址就是默认地址;
            MarketAddress marketAddress = addressService.findAddrById(userId, addressId);
            cartCheckoutData.setAddressId(marketAddress.getId() != null ? marketAddress.getId() : 0);
            cartCheckoutData.setCheckedAddress(marketAddress);
            // 得到所有选中的商品
            List<MarketCart> marketCarts = cartService.findCheckedGoods(userId);
            cartCheckoutData.setCheckedGoodsList(marketCarts);
            cartCheckoutData.setCartId(0);
            // 将购物车中的商品价格相加
            for (MarketCart marketCart : marketCarts) {
                money = money.add(marketCart.getPrice().multiply(new BigDecimal(marketCart.getNumber())));
            }
            // 没有优惠券，查找有多少优惠券可以使用, 有优惠券则查找使用的优惠券
            if (couponId <= 0) {
                List<MarketCouponUser> marketCoupons = couponUserService.findCouponById(userId, marketCarts);
                cartCheckoutData.setAvailableCouponLength(marketCoupons.size());
                cartCheckoutData.setUserCouponId(-1);
                cartCheckoutData.setCouponId(-1);
                cartCheckoutData.setCouponPrice(new BigDecimal(0));

            } else {
                // 这里是为了得到优惠券的折扣额度
                MarketCoupon marketCoupon = couponService.findCouponById(couponId);
                //这里是得到用户制定的userconpon
                MarketCouponUser couponUser = couponUserService.findByUserCouponId(userId, userCouponId);
                //这里是返回所有可以使用的couponuser信息
                List<MarketCouponUser> marketCoupons = couponUserService.findCouponById(userId, marketCarts);
                // 这里是返回可以使用的优惠券到底有几张
                cartCheckoutData.setAvailableCouponLength(marketCoupons.size());
                // 对各个价格的封装
                cartCheckoutData.setCouponPrice(marketCoupon.getDiscount() != null ? marketCoupon.getDiscount() : new BigDecimal(0));
                cartCheckoutData.setCouponId(marketCoupon.getId() != null ? marketCoupon.getId() : 0);
                cartCheckoutData.setUserCouponId(couponUser.getId() != null ? couponUser.getId() : 0);

                discount = discount.add(marketCoupon.getDiscount() != null ? marketCoupon.getDiscount() : new BigDecimal(0));

            }
            // 查找MarketGrouponRules通过GrouponRulesId查找
            MarketGrouponRules grouponRules = grouponRulesService.findById(grouponRulesId);
            cartCheckoutData.setGrouponRulesId(grouponRulesId != null ? grouponRulesId : 0);
            cartCheckoutData.setGrouponPrice(grouponRules.getDiscount() != null ? grouponRules.getDiscount() : new BigDecimal(0));
            discount = discount.add(grouponRules.getDiscount() != null ? grouponRules.getDiscount() : new BigDecimal(0));
            // 这里是得到运费，和订单金额大于多少就不用运费了
            if (money.compareTo(new BigDecimal(systemConfig.get("market_express_freight_min"))) >= 0) {
                cartCheckoutData.setFreightPrice(new BigDecimal(0));
                cartCheckoutData.setGoodsTotalPrice(money);
                cartCheckoutData.setOrderTotalPrice(money.subtract(discount));
                cartCheckoutData.setActualPrice(money.subtract(discount));
            } else {
                money = money.add(new BigDecimal(systemConfig.get("market_express_freight_value")));
                cartCheckoutData.setFreightPrice(new BigDecimal(systemConfig.get("market_express_freight_value")));
                cartCheckoutData.setGoodsTotalPrice(money);
                cartCheckoutData.setOrderTotalPrice(money.subtract(discount));
                cartCheckoutData.setActualPrice(money.subtract(discount));
            }

        } else {
            // 这个else的作用就是当前端传来fastadd提交的订单，只有一个物品，cartId是具体的
            // 其他 和前面判定方式一模一样，除了订单返回的是一个对象
            MarketCart marketCart = cartService.findByCartId(cartId);
            MarketAddress marketAddress = addressService.findAddrById(userId, addressId);
            cartCheckoutData.setAddressId(marketAddress.getId() != null ? marketAddress.getId() : 0); //这个方法出现了很多三目运算是因为当表中什么都没有的时候，
                                                                                                        // 返回的封装对象是null，会报错，所以什么都不返回给前端
            cartCheckoutData.setCheckedAddress(marketAddress);

            List<MarketCart> marketCarts = new ArrayList<>();
            marketCarts.add(marketCart);
            cartCheckoutData.setCheckedGoodsList(marketCarts);
            cartCheckoutData.setCartId(marketCart.getId());

            money = money.add(marketCart.getPrice().multiply(new BigDecimal(marketCart.getNumber())));


            if (couponId <= 0) {

                List<MarketCouponUser> marketCoupons = couponUserService.findCouponById(userId, marketCarts);
                cartCheckoutData.setAvailableCouponLength(marketCoupons.size());
                cartCheckoutData.setUserCouponId(-1);
                cartCheckoutData.setCouponId(-1);
                cartCheckoutData.setCouponPrice(new BigDecimal(0));

            } else {

                MarketCoupon marketCoupon = couponService.findCouponById(couponId);
                MarketCouponUser couponUser = couponUserService.findByUserCouponId(userId, userCouponId);
                List<MarketCouponUser> marketCoupons = couponUserService.findCouponById(userId, marketCarts);
                cartCheckoutData.setAvailableCouponLength(marketCoupons.size());

                cartCheckoutData.setCouponPrice(marketCoupon.getDiscount() != null ? marketCoupon.getDiscount() : new BigDecimal(0));
                cartCheckoutData.setCouponId(marketCoupon.getId() != null ? marketCoupon.getId() : 0);
                cartCheckoutData.setUserCouponId(couponUser.getId() != null ? couponUser.getId() : 0);
                discount = discount.add(marketCoupon.getDiscount() != null ? marketCoupon.getDiscount() : new BigDecimal(0));


            }

            MarketGrouponRules grouponRules = grouponRulesService.findById(grouponRulesId);
            cartCheckoutData.setGrouponRulesId(grouponRulesId != null ? grouponRulesId : 0);
            cartCheckoutData.setGrouponPrice(grouponRules.getDiscount() != null ? grouponRules.getDiscount() : new BigDecimal(0));
            discount = discount.add(grouponRules.getDiscount() != null ? grouponRules.getDiscount() : new BigDecimal(0));

            if (money.compareTo(new BigDecimal(systemConfig.get("market_express_freight_min"))) >= 0) {
                cartCheckoutData.setFreightPrice(new BigDecimal(0));
                cartCheckoutData.setGoodsTotalPrice(money);
                cartCheckoutData.setOrderTotalPrice(money.subtract(discount));
                cartCheckoutData.setActualPrice(money.subtract(discount));
            } else {
                money = money.add(new BigDecimal(systemConfig.get("market_express_freight_value")));
                cartCheckoutData.setFreightPrice(new BigDecimal(systemConfig.get("market_express_freight_value")));
                cartCheckoutData.setGoodsTotalPrice(money);
                cartCheckoutData.setOrderTotalPrice(money.subtract(discount));
                cartCheckoutData.setActualPrice(money.subtract(discount));
            }

        }
        return BaseRespVo.ok(cartCheckoutData);
    }

    @PostMapping("update")
    public BaseRespVo update(@RequestBody Map map) {
        //1. 根据请求参数更新number数据
        cartService.updateNumber(map);
        return BaseRespVo.ok(null);
    }

    @PostMapping("delete")
    public BaseRespVo delete(@RequestBody Map<String, List<Integer>> map) {
        //获取userId
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            Integer userId = (Integer) subject.getPrincipal();

            //1. 根据请求参数进行删除操作
            cartService.deleteByProductIds(map);

            //2. 再查询一下购物车信息
            CartIndexData data = cartService.cartIndex(userId);

            //3. 最后响应一下data数据
            return BaseRespVo.ok(data);
        } else {
            return BaseRespVo.unAuthc();
        }
    }
}
